#include "g_local.h"
#include "bots_game2cgame.h"

#include "bots_local.h"
#include "bots_captain.h"
#include "bots_scientist.h"
#include "bots_bodyguard.h"
#include "bots_sniper.h"
#include "bots_soldier.h"
#include "bots_berzerker.h"
#include "bots_infiltrator.h"
#include "bots_kamikazee.h"
#include "bots_nurse.h"

// Ad hoc kludge for those 2 classes. A powerup or something like that coulda been used
// Anyway it needs to be broadcasted to everyone, soooo....
qboolean bots_updateConfigString_NURSE(gentity_t* ent,bots_game2cgame_t *p) {
	// Poison is broadcasted
	if (p->onion.nurse.bits & (1<<BOTS_G2CG_NURSE_POISON)) {
			trap_SetConfigstring(CS_BOTS_CLIENT + ent->s.clientNum, 
				va("c\\%i\\lev\\%i\\p\\1", 
				ent->bots_class,
				ent->client->pers.classlevel));
			return qtrue;
	}
	return qfalse;
}

qboolean bots_updateConfigString_INFILTRATOR(gentity_t* ent,bots_game2cgame_t *p) {
	// If disguised as the other team, broadcast
	if (p->onion.infiltrator.sDisguiseTime >= 0) {
			trap_SetConfigstring(CS_BOTS_CLIENT + ent->s.clientNum, 
				va("c\\%i\\lev\\%i\\ed\\1", 
				ent->bots_class,
				ent->client->pers.classlevel));
			return qtrue;
	}
	return qfalse;
}

// Update the BotS config string
void bots_updateConfigString(gentity_t* ent,bots_game2cgame_t *p) {
	if (ent->client) {
		// Kludge needed
		switch (ent->bots_class) {
		case BOTS_NURSE:
			if (bots_updateConfigString_NURSE(ent,p))	return;
			break;
		case BOTS_INFILTRATOR:
			if (bots_updateConfigString_INFILTRATOR(ent,p))	return;
			break;
		}
		trap_SetConfigstring(CS_BOTS_CLIENT + ent->s.clientNum, 
			va("c\\%i\\lev\\%i", 
			ent->bots_class,
			ent->client->pers.classlevel	// Duplicated... Bah!
			));
	}
}

/*
void bots_WriteConfigString(gentity_t *ent) {
	bots_updateConfigString(ent);
}
*/

// Because all the state for a class is not maintained, we have to do tricky games
// I hate to expose structures like that
// See its companion the macro BOTS_G2CG_GETDATA
void *bots_g2cg_getClassSection(gentity_t* ent) {
	return (void *) &((bots_game2cgame_t *)&ent->client->ps.stats[STAT_GAME2CGAME])->onion.generic;
}

// Update the common payload
void bots_updateClientData_common(gentity_t *ent, bots_game2cgame_t *p) {
	int*		promotech;


	// Promo/Tech points
	promotech = BOTS_get_promotech_points(ent->bots_team);
	p->ucPromoPoints	= BOTS_CLAMP_UC(promotech[0]);			// Slightly truncated ;)
	p->ucTechPoints		= BOTS_CLAMP_UC(promotech[1]);

	// Powerups
	p->ucPowerup		= ent->client->i_powerup; // No need to clamp, it's signed. Bah!
		// Double argh! LCC generate an unknown token on that one :( (unsigned short)
}

void bots_updateClientData(gentity_t *ent) {
	if (ent->client) {
		bots_game2cgame_t	*p = (bots_game2cgame_t *) &ent->client->ps.stats[STAT_GAME2CGAME];

		// Common data like promo points...etc...
		bots_updateClientData_common(ent,p);
		switch (ent->bots_class) 
		{
		case BOTS_CAPTAIN:
			bots_updateClientData_captain(ent,&p->onion.captain);
			break;
		case BOTS_BODYGUARD:
			bots_updateClientData_bodyguard(ent,&p->onion.bodyguard);
			break;
		case BOTS_SNIPER:
			bots_updateClientData_sniper(ent,&p->onion.sniper);
			break;
		case BOTS_SOLDIER:
			bots_updateClientData_soldier(ent,&p->onion.soldier);
			break;
		case BOTS_BERZERKER:
			bots_updateClientData_berzerker(ent,&p->onion.berzerker);
			break;
		case BOTS_INFILTRATOR:
			bots_updateClientData_infiltrator(ent,&p->onion.infiltrator);
			break;
		case BOTS_KAMIKAZEE:
			bots_updateClientData_kamikazee(ent,&p->onion.kamikazee);
			break;
		case BOTS_NURSE:
			bots_updateClientData_nurse(ent,&p->onion.nurse);
			break;
		case BOTS_SCIENTIST:
			bots_updateClientData_scientist(ent,&p->onion.scientist);
			break;
		default:
			memset(&p->onion.generic,'\0',sizeof(bots_g2cg_generic_t));	// Keep finger crossed and mismatched sizes away
			break;
		}

		// Class & Level + kludge for nurse&inf
		bots_updateConfigString(ent,p);
	}
}

